/**
* @private
* Uses the {@link Ext.device.Camera} API.
*/
Ext.define('Ext.file.file.PhoneGap', {
    extend: 'Ext.file.file.Abstract',
    config: {

        PG: {}

    },

    constructor: function (config) {

        this.initConfig(config);
        /**
        * List of resource files loaded by PhoneGap.
        * This is used to ensure JS and other files are loaded only once.
        */
        //oPhoneGap.resources = { base: true };

        /**
        * Determine if resource has been loaded by PhoneGap
        *
        * @param name
        * @return
        */
        var oPhoneGap = {};
        if (typeof (PhoneGap) === 'object')
            oPhoneGap = PhoneGap;
        if (typeof oPhoneGap.queue === "undefined")
            oPhoneGap.queue = {};
        if (typeof oPhoneGap.queue.ready === "undefined")
            oPhoneGap.queue.ready = true;
        if (typeof oPhoneGap.queue.commands === "undefined")
            oPhoneGap.queue.commands = [];
        if (typeof oPhoneGap.queue.timer === "undefined")
            oPhoneGap.queue.timer = null;
        if (typeof oPhoneGap.resources === "undefined")
            oPhoneGap.resources = {};
        if (typeof oPhoneGap.resources.base === "undefined")
            oPhoneGap.resources.base = true;
        if (typeof oPhoneGap._constructors === "undefined")
            oPhoneGap._constructors = [];

        if (typeof oPhoneGap.hasResource !== 'function')
            oPhoneGap.hasResource = function (name) {
                return oPhoneGap.resources[name];
            };
        if (typeof (DeviceInfo) !== 'object')
            DeviceInfo = {};
        /**
        * Boolean flag indicating if the PhoneGap API is available and initialized.
        */
        // TODO: Remove this, it is unused here ... -jm
        if (typeof oPhoneGap.available != "boolean") {

            oPhoneGap.available = DeviceInfo.uuid != undefined;
        }
        /**
        * Add a resource to list of loaded resources by PhoneGap
        *
        * @param name
        */
        if (typeof oPhoneGap.addResource !== 'function')
            oPhoneGap.addResource = function (name) {
                oPhoneGap.resources[name] = true;
            };
        // centralized callbacks
        if (typeof oPhoneGap.callbackId != "undefined")
            oPhoneGap.callbackId = 0;
        if (typeof oPhoneGap.callbacks != "undefined")
            oPhoneGap.callbacks = {};
        if (typeof oPhoneGap.callbackStatus != "undefined")
            oPhoneGap.callbackStatus = {
                NO_RESULT: 0,
                OK: 1,
                CLASS_NOT_FOUND_EXCEPTION: 2,
                ILLEGAL_ACCESS_EXCEPTION: 3,
                INSTANTIATION_EXCEPTION: 4,
                MALFORMED_URL_EXCEPTION: 5,
                IO_EXCEPTION: 6,
                INVALID_ACTION: 7,
                JSON_EXCEPTION: 8,
                ERROR: 9
            };
        // The iOS notification.js implementation doesn't match the normalized PhoneGap javascript.
        // This shim does the necessary translation to allow the native code to work with the new javascript.
        // The underlying native code should be updated and this shim should be removed.
        if (typeof oPhoneGap.shim !== 'function')
            oPhoneGap.shim = function (args) {
                var SERVICE = 2,
                ACTION = 3,
                ARGS = 4,
                STOP_PROCESSING = -1;

                if (args[SERVICE] === "Notification") {

                    if (args[ACTION] === "confirm") {
                        args[ACTION] = "alert"; // confirm is the same as alert
                    }

                    if (args[ACTION] === "alert") {
                        // translate some of the action arguments into a dictionary
                        // [message, _title, _buttonLabel] to [message,{ "title": _title, "buttonLabel": _buttonLabel}]
                        args[ARGS] = [args[ARGS][0], {
                            "title": args[ARGS][1],
                            "buttonLabel": args[ARGS][2]
                        }];
                    } else if (args[ACTION] === "beep") {
                        // beep.wav must be in www folder
                        (new Media('beep.wav').play());
                        return STOP_PROCESSING;
                    }
                }
                return args;
            };
        /**
        * Execute a PhoneGap command in a queued fashion, to ensure commands do not
        * execute with any race conditions, and only run when PhoneGap is ready to
        * receive them.
        *
        */
        if (typeof oPhoneGap.exec !== 'function')
            oPhoneGap.exec = function () {

                var args = oPhoneGap.shim(arguments);
                if (args === -1) {
                    return;
                }

                oPhoneGap.queue.commands.push(args);
                if (oPhoneGap.queue.timer == null)
                    oPhoneGap.queue.timer = setInterval(oPhoneGap.run_command, 10);
            };

        /**
        * Internal function used to dispatch the request to PhoneGap.  It processes the
        * command queue and executes the next command on the list.  Simple parameters are passed
        * as arguments on the url.  JavaScript objects converted into a JSON string and passed as a
        * query string argument of the url.
        * Arguments may be in one of two formats:
        *   FORMAT ONE (preferable)
        * The native side will call PhoneGap.callbackSuccess or PhoneGap.callbackError,
        * depending upon the result of the action.
        *
        * @param {Function} success    The success callback
        * @param {Function} fail       The fail callback
        * @param {String} service      The name of the service to use
        * @param {String} action		The name of the action to use
        * @param {String[]} [args]     Zero or more arguments to pass to the method
        *  	
        * FORMAT TWO
        * @param {String} command Command to be run in PhoneGap, e.g. "ClassName.method"
        * @param {String[]} [args] Zero or more arguments to pass to the method
        * object parameters are passed as an array object [object1, object2] each object will be passed as JSON strings 
        * @private
        */
        if (typeof oPhoneGap.run_command !== 'function')
            oPhoneGap.run_command = function () {
                if (!oPhoneGap.available || !oPhoneGap.queue.ready)
                    return;

                oPhoneGap.queue.ready = false;

                if (!this.gapBridge) {
                    this.gapBridge = document.createElement("iframe");
                    this.gapBridge.setAttribute("style", "display:none;");
                    this.gapBridge.setAttribute("height", "0px");
                    this.gapBridge.setAttribute("width", "0px");
                    this.gapBridge.setAttribute("frameborder", "0");
                    document.documentElement.appendChild(this.gapBridge);
                }

                var args = oPhoneGap.queue.commands.shift();
                if (oPhoneGap.queue.commands.length == 0) {
                    clearInterval(oPhoneGap.queue.timer);
                    oPhoneGap.queue.timer = null;
                }

                var service;
                var callbackId = null;
                var start = 0;
                try {
                    if (args[0] == null || typeof args[0] === "function") {
                        var success = args[0];
                        var fail = args[1];
                        service = args[2] + "." + args[3];
                        args = args[4];  //array of arguments to 
                        callbackId = service + oPhoneGap.callbackId++;
                        if (success || fail) {
                            oPhoneGap.callbacks[callbackId] = { success: success, fail: fail };
                        }
                    } else {
                        service = args[0];
                        start = 1;
                    }

                    var uri = [];
                    var dict = null;

                    for (var i = start; i < args.length; i++) {
                        var arg = args[i];
                        if (arg == undefined || arg == null)
                            continue;
                        if (typeof (arg) == 'object')
                            dict = arg;
                        else
                            uri.push(encodeURIComponent(arg));
                    }
                    var next = callbackId != null ? ("/" + callbackId + "/") : "/";
                    var url = "gap://" + service + next + uri.join("/");

                    if (dict != null) {
                        url += "?" + encodeURIComponent(JSON.stringify(dict));
                    }

                    this.gapBridge.src = url;

                } catch (e) {
                    console.log("PhoneGapExec Error: " + e);
                }


            };
        /**
        * Called by native code when returning successful result from an action.
        *
        * @param callbackId
        * @param args
        *		args.status - PhoneGap.callbackStatus
        *		args.message - return value
        *		args.keepCallback - 0 to remove callback, 1 to keep callback in PhoneGap.callbacks[]
        */
        if (typeof oPhoneGap.callbackSuccess !== 'function')
            oPhoneGap.callbackSuccess = function (callbackId, args) {
                if (oPhoneGap.callbacks[callbackId]) {

                    // If result is to be sent to callback
                    if (args.status == oPhoneGap.callbackStatus.OK) {
                        try {
                            if (oPhoneGap.callbacks[callbackId].success) {
                                oPhoneGap.callbacks[callbackId].success(args.message);
                            }
                        }
                        catch (e) {
                            console.log("Error in success callback: " + callbackId + " = " + e);
                        }
                    }

                    // Clear callback if not expecting any more results
                    if (!args.keepCallback) {
                        delete oPhoneGap.callbacks[callbackId];
                    }
                }
            };

        /**
        * Called by native code when returning error result from an action.
        *
        * @param callbackId
        * @param args
        */
        if (typeof oPhoneGap.callbackError !== 'function')
            oPhoneGap.callbackError = function (callbackId, args) {
                if (oPhoneGap.callbacks[callbackId]) {
                    try {
                        if (oPhoneGap.callbacks[callbackId].fail) {
                            oPhoneGap.callbacks[callbackId].fail(args.message);
                        }
                    }
                    catch (e) {
                        console.log("Error in error callback: " + callbackId + " = " + e);
                    }

                    // Clear callback if not expecting any more results
                    if (!args.keepCallback) {
                        delete oPhoneGap.callbacks[callbackId];
                    }
                }
            };

        /**
        * Does a deep clone of the object.
        *
        * @param obj
        * @return
        */
        if (typeof oPhoneGap.clone !== 'function')
            oPhoneGap.clone = function (obj) {
                if (!obj) {
                    return obj;
                }

                if (obj instanceof Array) {
                    var retVal = new Array();
                    for (var i = 0; i < obj.length; ++i) {
                        retVal.push(oPhoneGap.clone(obj[i]));
                    }
                    return retVal;
                }

                if (obj instanceof Function) {
                    return obj;
                }

                if (!(obj instanceof Object)) {
                    return obj;
                }

                if (obj instanceof Date) {
                    return obj;
                }

                retVal = new Object();
                for (i in obj) {
                    if (!(i in retVal) || retVal[i] != obj[i]) {
                        retVal[i] = oPhoneGap.clone(obj[i]);
                    }
                }
                return retVal;
            };

        // Intercept calls to document.addEventListener and watch for unload

        oPhoneGap.m_document_addEventListener = document.addEventListener;

        document.addEventListener = function (evt, handler, capture) {
            var e = evt.toLowerCase();
            if (e === 'unload') {
                oPhoneGap.onUnload = function (e) { return handler(e); };
            }
            else {
                oPhoneGap.m_document_addEventListener.call(document, evt, handler, capture);
            }
        };

        // Intercept calls to document.removeEventListener and watch for events that 
        // are generated by PhoneGap native code

        oPhoneGap.m_document_removeEventListener = document.removeEventListener;

        document.removeEventListener = function (evt, handler, capture) {
            var e = evt.toLowerCase();

            if (e === 'unload') {
                oPhoneGap.onUnload = null;
            }

            oPhoneGap.m_document_removeEventListener.call(document, evt, handler, capture);
        };

        /**
        * Method to fire event from native code
        */
        if (typeof oPhoneGap.fireEvent !== 'function')
            oPhoneGap.fireEvent = function (type, target) {
                var e = document.createEvent('Events');
                e.initEvent(type);

                target = target || document;
                if (target.dispatchEvent === undefined) { // ie window.dispatchEvent is undefined in iOS 3.x
                    target = document;
                }

                target.dispatchEvent(e);
            };

        //
        //file
        //
        if (!oPhoneGap.hasResource("file")) {
            oPhoneGap.addResource("file");
            /**
            * This class provides generic read and write access to the mobile device file system.
            * They are not used to read files from a server.
            */
            /**
            * This class provides some useful information about a file.
            * This is the fields returned when navigator.fileMgr.getFileProperties() 
            * is called.
            */
            FileProperties = function (filePath) {
                this.filePath = filePath;
                this.size = 0;
                this.lastModifiedDate = null;
            }
            /**
            * Represents a single file.
            * 
            * name {DOMString} name of the file, without path information
            * fullPath {DOMString} the full path of the file, including the name
            * type {DOMString} mime type
            * lastModifiedDate {Date} last modified date
            * size {Number} size of the file in bytes
            */
            File = function (name, fullPath, type, lastModifiedDate, size) {
                this.name = name || null;
                this.fullPath = fullPath || null;
                this.type = type || null;
                this.lastModifiedDate = lastModifiedDate || null;
                this.size = size || 0;
            }
            /**
            * Create an event object since we can't set target on DOM event.
            *
            * @param type
            * @param target
            *
            */
            File._createEvent = function (type, target) {
                // Can't create event object, since we can't set target (its readonly)
                //var evt = document.createEvent('Events');
                //evt.initEvent("onload", false, false);
                var evt = { "type": type };
                evt.target = target;
                return evt;
            };

            FileError = function () {
                this.code = null;
            }

            // File error codes
            // Found in DOMException
            FileError.NOT_FOUND_ERR = 1;
            FileError.SECURITY_ERR = 2;
            FileError.ABORT_ERR = 3;

            // Added by this specification
            FileError.NOT_READABLE_ERR = 4;
            FileError.ENCODING_ERR = 5;
            FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
            FileError.INVALID_STATE_ERR = 7;
            FileError.SYNTAX_ERR = 8;
            FileError.INVALID_MODIFICATION_ERR = 9;
            FileError.QUOTA_EXCEEDED_ERR = 10;
            FileError.TYPE_MISMATCH_ERR = 11;
            FileError.PATH_EXISTS_ERR = 12;

            //-----------------------------------------------------------------------------
            // File manager
            //-----------------------------------------------------------------------------

            FileMgr = function () {
            }

            FileMgr.prototype.testFileExists = function (fileName, successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "testFileExists", [fileName]);
            };

            FileMgr.prototype.testDirectoryExists = function (dirName, successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "testDirectoryExists", [dirName]);
            };

            FileMgr.prototype.getFreeDiskSpace = function (successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "getFreeDiskSpace", []);
            };

            FileMgr.prototype.writeAsText = function (fileName, data, bAppend, successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "write", [fileName, data, bAppend ? 1 : 0]);
            };

            FileMgr.prototype.write = function (fileName, data, position, successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "write", [fileName, data, position]);
            };

            FileMgr.prototype.truncate = function (fileName, size, successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "truncateFile", [fileName, size]);
            };

            FileMgr.prototype.readAsText = function (fileName, encoding, successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "readFile", [fileName, encoding]);
            };

            FileMgr.prototype.readAsDataURL = function (fileName, successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "readAsDataURL", [fileName]);
            };

            //PhoneGap.addConstructor(function() {
            if (typeof navigator.fileMgr === "undefined") {
                navigator.fileMgr = new FileMgr();
            }
            //});
            //-----------------------------------------------------------------------------
            // File Reader
            //-----------------------------------------------------------------------------

            /**
            * This class reads the mobile device file system.
            *
            */
            FileReader = function () {
                this.fileName = "";

                this.readyState = 0;

                // File data
                this.result = null;

                // Error
                this.error = null;

                // Event handlers
                this.onloadstart = null;    // When the read starts.
                this.onprogress = null;     // While reading (and decoding) file or fileBlob data, and reporting partial file data (progess.loaded/progress.total)
                this.onload = null;         // When the read has successfully completed.
                this.onerror = null;        // When the read has failed (see errors).
                this.onloadend = null;      // When the request has completed (either in success or failure).
                this.onabort = null;        // When the read has been aborted. For instance, by invoking the abort() method.
            }

            // States
            FileReader.EMPTY = 0;
            FileReader.LOADING = 1;
            FileReader.DONE = 2;

            /**
            * Abort reading file.
            */
            FileReader.prototype.abort = function () {
                var evt;
                this.readyState = FileReader.DONE;
                this.result = null;

                // set error
                var error = new FileError();
                error.code = error.ABORT_ERR;
                this.error = error;

                // If error callback
                if (typeof this.onerror === "function") {
                    evt = File._createEvent("error", this);
                    this.onerror(evt);
                }
                // If abort callback
                if (typeof this.onabort === "function") {
                    evt = File._createEvent("abort", this);
                    this.onabort(evt);
                }
                // If load end callback
                if (typeof this.onloadend === "function") {
                    evt = File._createEvent("loadend", this);
                    this.onloadend(evt);
                }
            };

            /**
            * Read text file.
            *
            * @param file          The name of the file
            * @param encoding      [Optional] (see http://www.iana.org/assignments/character-sets)
            */
            FileReader.prototype.readAsText = function (file, encoding) {
                this.fileName = "";
                if (typeof file.fullPath === "undefined") {
                    this.fileName = file;
                } else {
                    this.fileName = file.fullPath;
                }

                // LOADING state
                this.readyState = FileReader.LOADING;

                // If loadstart callback
                if (typeof this.onloadstart === "function") {
                    var evt = File._createEvent("loadstart", this);
                    this.onloadstart(evt);
                }

                // Default encoding is UTF-8
                var enc = encoding ? encoding : "UTF-8";

                var me = this;

                // Read file
                navigator.fileMgr.readAsText(this.fileName, enc,

                // Success callback
                        function (r) {
                            var evt;

                            // If DONE (cancelled), then don't do anything
                            if (me.readyState === FileReader.DONE) {
                                return;
                            }

                            // Save result
                            me.result = decodeURIComponent(r);

                            // If onload callback
                            if (typeof me.onload === "function") {
                                evt = File._createEvent("load", me);
                                me.onload(evt);
                            }

                            // DONE state
                            me.readyState = FileReader.DONE;

                            // If onloadend callback
                            if (typeof me.onloadend === "function") {
                                evt = File._createEvent("loadend", me);
                                me.onloadend(evt);
                            }
                        },

                // Error callback
                        function (e) {
                            var evt;
                            // If DONE (cancelled), then don't do anything
                            if (me.readyState === FileReader.DONE) {
                                return;
                            }

                            // Save error
                            me.error = e;

                            // If onerror callback
                            if (typeof me.onerror === "function") {
                                evt = File._createEvent("error", me);
                                me.onerror(evt);
                            }

                            // DONE state
                            me.readyState = FileReader.DONE;

                            // If onloadend callback
                            if (typeof me.onloadend === "function") {
                                evt = File._createEvent("loadend", me);
                                me.onloadend(evt);
                            }
                        }
                        );
            };


            /**
            * Read file and return data as a base64 encoded data url.
            * A data url is of the form:
            *      data:[<mediatype>][;base64],<data>
            *
            * @param file          {File} File object containing file properties
            */
            FileReader.prototype.readAsDataURL = function (file) {
                this.fileName = "";

                if (typeof file.fullPath === "undefined") {
                    this.fileName = file;
                } else {
                    this.fileName = file.fullPath;
                }

                // LOADING state
                this.readyState = FileReader.LOADING;

                // If loadstart callback
                if (typeof this.onloadstart === "function") {
                    var evt = File._createEvent("loadstart", this);
                    this.onloadstart(evt);
                }

                var me = this;

                // Read file
                navigator.fileMgr.readAsDataURL(this.fileName,

                // Success callback
                        function (r) {
                            var evt;

                            // If DONE (cancelled), then don't do anything
                            if (me.readyState === FileReader.DONE) {
                                return;
                            }

                            // Save result
                            me.result = r;

                            // If onload callback
                            if (typeof me.onload === "function") {
                                evt = File._createEvent("load", me);
                                me.onload(evt);
                            }

                            // DONE state
                            me.readyState = FileReader.DONE;

                            // If onloadend callback
                            if (typeof me.onloadend === "function") {
                                evt = File._createEvent("loadend", me);
                                me.onloadend(evt);
                            }
                        },

                // Error callback
                        function (e) {
                            var evt;
                            // If DONE (cancelled), then don't do anything
                            if (me.readyState === FileReader.DONE) {
                                return;
                            }

                            // Save error
                            me.error = e;

                            // If onerror callback
                            if (typeof me.onerror === "function") {
                                evt = File._createEvent("error", me);
                                me.onerror(evt);
                            }

                            // DONE state
                            me.readyState = FileReader.DONE;

                            // If onloadend callback
                            if (typeof me.onloadend === "function") {
                                evt = File._createEvent("loadend", me);
                                me.onloadend(evt);
                            }
                        }
                        );
            };

            /**
            * Read file and return data as a binary data.
            *
            * @param file          The name of the file
            */
            FileReader.prototype.readAsBinaryString = function (file) {
                // TODO - Can't return binary data to browser.
                this.fileName = file;
            };

            /**
            * Read file and return data as a binary data.
            *
            * @param file          The name of the file
            */
            FileReader.prototype.readAsArrayBuffer = function (file) {
                // TODO - Can't return binary data to browser.
                this.fileName = file;
            };

            //-----------------------------------------------------------------------------
            // File Writer
            //-----------------------------------------------------------------------------

            /**
            * This class writes to the mobile device file system.
            *
            @param file {File} a File object representing a file on the file system
            */
            FileWriter = function (file) {
                this.fileName = "";
                this.length = 0;
                if (file) {
                    this.fileName = file.fullPath || file;
                    this.length = file.size || 0;
                }

                // default is to write at the beginning of the file
                this.position = 0;

                this.readyState = 0; // EMPTY

                this.result = null;

                // Error
                this.error = null;

                // Event handlers
                this.onwritestart = null; // When writing starts
                this.onprogress = null; 	// While writing the file, and reporting partial file data
                this.onwrite = null; 	// When the write has successfully completed.
                this.onwriteend = null; 	// When the request has completed (either in success or failure).
                this.onabort = null; 	// When the write has been aborted. For instance, by invoking the abort() method.
                this.onerror = null; 	// When the write has failed (see errors).
            }

            // States
            FileWriter.INIT = 0;
            FileWriter.WRITING = 1;
            FileWriter.DONE = 2;

            /**
            * Abort writing file.
            */
            FileWriter.prototype.abort = function () {
                // check for invalid state
                if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) {
                    throw FileError.INVALID_STATE_ERR;
                }

                // set error
                var error = new FileError(), evt;
                error.code = error.ABORT_ERR;
                this.error = error;

                // If error callback
                if (typeof this.onerror === "function") {
                    evt = File._createEvent("error", this);
                    this.onerror(evt);
                }
                // If abort callback
                if (typeof this.onabort === "function") {
                    evt = File._createEvent("abort", this);
                    this.onabort(evt);
                }

                this.readyState = FileWriter.DONE;

                // If write end callback
                if (typeof this.onwriteend == "function") {
                    evt = File._createEvent("writeend", this);
                    this.onwriteend(evt);
                }
            };

            /**
            * @Deprecated: use write instead
            * 
            * @param file to write the data to
            * @param text to be written
            * @param bAppend if true write to end of file, otherwise overwrite the file
            */
            FileWriter.prototype.writeAsText = function (file, text, bAppend) {
                // Throw an exception if we are already writing a file
                if (this.readyState === FileWriter.WRITING) {
                    throw FileError.INVALID_STATE_ERR;
                }

                if (bAppend !== true) {
                    bAppend = false; // for null values
                }

                this.fileName = file;

                // WRITING state
                this.readyState = FileWriter.WRITING;

                var me = this;

                // If onwritestart callback
                if (typeof me.onwritestart === "function") {
                    var evt = File._createEvent("writestart", me);
                    me.onwritestart(evt);
                }


                // Write file 
                navigator.fileMgr.writeAsText(file, text, bAppend,
                // Success callback
                        function (r) {
                            var evt;

                            // If DONE (cancelled), then don't do anything
                            if (me.readyState === FileWriter.DONE) {
                                return;
                            }

                            // Save result
                            me.result = r;

                            // If onwrite callback
                            if (typeof me.onwrite === "function") {
                                evt = File._createEvent("write", me);
                                me.onwrite(evt);
                            }

                            // DONE state
                            me.readyState = FileWriter.DONE;

                            // If onwriteend callback
                            if (typeof me.onwriteend === "function") {
                                evt = File._createEvent("writeend", me);
                                me.onwriteend(evt);
                            }
                        },

                // Error callback
                        function (e) {
                            var evt;

                            // If DONE (cancelled), then don't do anything
                            if (me.readyState === FileWriter.DONE) {
                                return;
                            }

                            // Save error
                            me.error = e;

                            // If onerror callback
                            if (typeof me.onerror === "function") {
                                evt = File._createEvent("error", me);
                                me.onerror(evt);
                            }

                            // DONE state
                            me.readyState = FileWriter.DONE;

                            // If onwriteend callback
                            if (typeof me.onwriteend === "function") {
                                evt = File._createEvent("writeend", me);
                                me.onwriteend(evt);
                            }
                        }
                    );
            };

            /**
            * Writes data to the file
            *  
            * @param text to be written
            */
            FileWriter.prototype.write = function (text) {
                // Throw an exception if we are already writing a file
                if (this.readyState === FileWriter.WRITING) {
                    throw FileError.INVALID_STATE_ERR;
                }

                // WRITING state
                this.readyState = FileWriter.WRITING;

                var me = this;

                // If onwritestart callback
                if (typeof me.onwritestart === "function") {
                    var evt = File._createEvent("writestart", me);
                    me.onwritestart(evt);
                }

                // Write file
                navigator.fileMgr.write(this.fileName, text, this.position,

                // Success callback
                        function (r) {
                            var evt;
                            // If DONE (cancelled), then don't do anything
                            if (me.readyState === FileWriter.DONE) {
                                return;
                            }


                            // position always increases by bytes written because file would be extended
                            me.position += r;
                            // The length of the file is now where we are done writing.
                            me.length = me.position;

                            // If onwrite callback
                            if (typeof me.onwrite === "function") {
                                evt = File._createEvent("write", me);
                                me.onwrite(evt);
                            }

                            // DONE state
                            me.readyState = FileWriter.DONE;

                            // If onwriteend callback
                            if (typeof me.onwriteend === "function") {
                                evt = File._createEvent("writeend", me);
                                me.onwriteend(evt);
                            }
                        },

                // Error callback
                        function (e) {
                            var evt;

                            // If DONE (cancelled), then don't do anything
                            if (me.readyState === FileWriter.DONE) {
                                return;
                            }

                            // Save error
                            me.error = e;

                            // If onerror callback
                            if (typeof me.onerror === "function") {
                                evt = File._createEvent("error", me);
                                me.onerror(evt);
                            }

                            // DONE state
                            me.readyState = FileWriter.DONE;

                            // If onwriteend callback
                            if (typeof me.onwriteend === "function") {
                                evt = File._createEvent("writeend", me);
                                me.onwriteend(evt);
                            }
                        }
                        );

            };

            /** 
            * Moves the file pointer to the location specified.
            * 
            * If the offset is a negative number the position of the file 
            * pointer is rewound.  If the offset is greater than the file 
            * size the position is set to the end of the file.  
            * 
            * @param offset is the location to move the file pointer to.
            */
            FileWriter.prototype.seek = function (offset) {
                // Throw an exception if we are already writing a file
                if (this.readyState === FileWriter.WRITING) {
                    throw FileError.INVALID_STATE_ERR;
                }

                if (!offset) {
                    return;
                }

                // See back from end of file.
                if (offset < 0) {
                    this.position = Math.max(offset + this.length, 0);
                }
                // Offset is bigger then file size so set position 
                // to the end of the file.
                else if (offset > this.length) {
                    this.position = this.length;
                }
                // Offset is between 0 and file size so set the position
                // to start writing.
                else {
                    this.position = offset;
                }
            };

            /** 
            * Truncates the file to the size specified.
            * 
            * @param size to chop the file at.
            */
            FileWriter.prototype.truncate = function (size) {
                // Throw an exception if we are already writing a file
                if (this.readyState === FileWriter.WRITING) {
                    throw FileError.INVALID_STATE_ERR;
                }
                // what if no size specified? 

                // WRITING state
                this.readyState = FileWriter.WRITING;

                var me = this;

                // If onwritestart callback
                if (typeof me.onwritestart === "function") {
                    var evt = File._createEvent("writestart", me);
                    me.onwritestart(evt);
                }

                // Write file
                navigator.fileMgr.truncate(this.fileName, size,

                // Success callback
                        function (r) {
                            var evt;
                            // If DONE (cancelled), then don't do anything
                            if (me.readyState === FileWriter.DONE) {
                                return;
                            }

                            // Update the length of the file
                            me.length = r;
                            me.position = Math.min(me.position, r);

                            // If onwrite callback
                            if (typeof me.onwrite === "function") {
                                evt = File._createEvent("write", me);
                                me.onwrite(evt);
                            }

                            // DONE state
                            me.readyState = FileWriter.DONE;

                            // If onwriteend callback
                            if (typeof me.onwriteend === "function") {
                                evt = File._createEvent("writeend", me);
                                me.onwriteend(evt);
                            }
                        },

                // Error callback
                        function (e) {
                            var evt;
                            // If DONE (cancelled), then don't do anything
                            if (me.readyState === FileWriter.DONE) {
                                return;
                            }

                            // Save error
                            me.error = e;

                            // If onerror callback
                            if (typeof me.onerror === "function") {
                                evt = File._createEvent("error", me);
                                me.onerror(evt);
                            }

                            // DONE state
                            me.readyState = FileWriter.DONE;

                            // If onwriteend callback
                            if (typeof me.onwriteend === "function") {
                                evt = File._createEvent("writeend", me);
                                me.onwriteend(evt);
                            }
                        }
                    );
            };

            LocalFileSystem = function () {
            };

            // File error codes
            LocalFileSystem.TEMPORARY = 0;
            LocalFileSystem.PERSISTENT = 1;
            LocalFileSystem.RESOURCE = 2;
            LocalFileSystem.APPLICATION = 3;

            /**
            * Requests a filesystem in which to store application data.
            * 
            * @param {int} type of file system being requested
            * @param {Function} successCallback is called with the new FileSystem
            * @param {Function} errorCallback is called with a FileError
            */
            LocalFileSystem.prototype.requestFileSystem = function (type, size, successCallback, errorCallback) {
                if (type < 0 || type > 3) {
                    if (typeof errorCallback == "function") {
                        errorCallback({
                            "code": FileError.SYNTAX_ERR
                        });
                    }
                }
                else {
                    oPhoneGap.exec(successCallback, errorCallback, "File", "requestFileSystem", [type, size]);
                }
            };

            /**
            * 
            * @param {DOMString} uri referring to a local file in a filesystem
            * @param {Function} successCallback is called with the new entry
            * @param {Function} errorCallback is called with a FileError
            */
            LocalFileSystem.prototype.resolveLocalFileSystemURI = function (uri, successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "resolveLocalFileSystemURI", [uri]);
            };

            /**
            * This function  is required as we need to convert raw 
            * JSON objects into concrete File and Directory objects.  
            * 
            * @param a JSON Objects that need to be converted to DirectoryEntry or FileEntry objects.
            * @returns an entry 
            */
            LocalFileSystem.prototype._castFS = function (pluginResult) {
                var entry = null;
                entry = new DirectoryEntry();
                entry.isDirectory = pluginResult.message.root.isDirectory;
                entry.isFile = pluginResult.message.root.isFile;
                entry.name = pluginResult.message.root.name;
                entry.fullPath = pluginResult.message.root.fullPath;
                pluginResult.message.root = entry;
                return pluginResult;
            }

            LocalFileSystem.prototype._castEntry = function (pluginResult) {
                var entry = null;
                if (pluginResult.message.isDirectory) {
                    entry = new DirectoryEntry();
                }
                else if (pluginResult.message.isFile) {
                    entry = new FileEntry();
                }
                entry.isDirectory = pluginResult.message.isDirectory;
                entry.isFile = pluginResult.message.isFile;
                entry.name = pluginResult.message.name;
                entry.fullPath = pluginResult.message.fullPath;
                pluginResult.message = entry;
                return pluginResult;
            }

            LocalFileSystem.prototype._castEntries = function (pluginResult) {
                var entries = pluginResult.message;
                var retVal = [];
                for (i = 0; i < entries.length; i++) {
                    retVal.push(window.localFileSystem._createEntry(entries[i]));
                }
                pluginResult.message = retVal;
                return pluginResult;
            }

            LocalFileSystem.prototype._createEntry = function (castMe) {
                var entry = null;
                if (castMe.isDirectory) {
                    entry = new DirectoryEntry();
                }
                else if (castMe.isFile) {
                    entry = new FileEntry();
                }
                entry.isDirectory = castMe.isDirectory;
                entry.isFile = castMe.isFile;
                entry.name = castMe.name;
                entry.fullPath = castMe.fullPath;
                return entry;

            }

            LocalFileSystem.prototype._castDate = function (pluginResult) {
                if (pluginResult.message.modificationTime) {
                    var metadataObj = new Metadata();

                    metadataObj.modificationTime = new Date(pluginResult.message.modificationTime);
                    pluginResult.message = metadataObj;
                }
                else if (pluginResult.message.lastModifiedDate) {
                    var file = new File();
                    file.size = pluginResult.message.size;
                    file.type = pluginResult.message.type;
                    file.name = pluginResult.message.name;
                    file.fullPath = pluginResult.message.fullPath;
                    file.lastModifiedDate = new Date(pluginResult.message.lastModifiedDate);
                    pluginResult.message = file;
                }

                return pluginResult;
            }
            LocalFileSystem.prototype._castError = function (pluginResult) {
                var fileError = new FileError();
                fileError.code = pluginResult.message;
                pluginResult.message = fileError;
                return pluginResult;
            }

            /**
            * Information about the state of the file or directory
            * 
            * {Date} modificationTime (readonly)
            */
            Metadata = function () {
                this.modificationTime = null;
            };

            /**
            * Supplies arguments to methods that lookup or create files and directories
            * 
            * @param {boolean} create file or directory if it doesn't exist 
            * @param {boolean} exclusive if true the command will fail if the file or directory exists
            */
            Flags = function (create, exclusive) {
                this.create = create || false;
                this.exclusive = exclusive || false;
            };

            /**
            * An interface representing a file system
            * 
            * {DOMString} name the unique name of the file system (readonly)
            * {DirectoryEntry} root directory of the file system (readonly)
            */
            FileSystem = function () {
                this.name = null;
                this.root = null;
            };

            /**
            * An interface representing a directory on the file system.
            * 
            * {boolean} isFile always false (readonly)
            * {boolean} isDirectory always true (readonly)
            * {DOMString} name of the directory, excluding the path leading to it (readonly)
            * {DOMString} fullPath the absolute full path to the directory (readonly)
            * {FileSystem} filesystem on which the directory resides (readonly)
            */
            DirectoryEntry = function () {
                this.isFile = false;
                this.isDirectory = true;
                this.name = null;
                this.fullPath = null;
                this.filesystem = null;
            };

            /**
            * Copies a directory to a new location
            * 
            * @param {DirectoryEntry} parent the directory to which to copy the entry
            * @param {DOMString} newName the new name of the entry, defaults to the current name
            * @param {Function} successCallback is called with the new entry
            * @param {Function} errorCallback is called with a FileError
            */
            DirectoryEntry.prototype.copyTo = function (parent, newName, successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "copyTo", [this.fullPath, parent, newName]);
            };

            /**
            * Looks up the metadata of the entry
            * 
            * @param {Function} successCallback is called with a Metadata object
            * @param {Function} errorCallback is called with a FileError
            */
            DirectoryEntry.prototype.getMetadata = function (successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "getMetadata", [this.fullPath]);
            };

            /**
            * Gets the parent of the entry
            * 
            * @param {Function} successCallback is called with a parent entry
            * @param {Function} errorCallback is called with a FileError
            */
            DirectoryEntry.prototype.getParent = function (successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "getParent", [this.fullPath]);
            };

            /**
            * Moves a directory to a new location
            * 
            * @param {DirectoryEntry} parent the directory to which to move the entry
            * @param {DOMString} newName the new name of the entry, defaults to the current name
            * @param {Function} successCallback is called with the new entry
            * @param {Function} errorCallback is called with a FileError
            */
            DirectoryEntry.prototype.moveTo = function (parent, newName, successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "moveTo", [this.fullPath, parent, newName]);
            };

            /**
            * Removes the entry
            * 
            * @param {Function} successCallback is called with no parameters
            * @param {Function} errorCallback is called with a FileError
            */
            DirectoryEntry.prototype.remove = function (successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "remove", [this.fullPath]);
            };

            /**
            * Returns a URI that can be used to identify this entry.
            * 
            * @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI.
            * @param {Function} successCallback is called with the new entry
            * @param {Function} errorCallback is called with a FileError
            */
            DirectoryEntry.prototype.toURI = function (mimeType, successCallback, errorCallback) {
                return "file://localhost" + this.fullPath;
                //oPhoneGap.exec(successCallback, errorCallback, "File", "toURI", [this.fullPath, mimeType]);
            };

            /**
            * Creates a new DirectoryReader to read entries from this directory
            */
            DirectoryEntry.prototype.createReader = function (successCallback, errorCallback) {
                return new DirectoryReader(this.fullPath);
            };

            /**
            * Creates or looks up a directory
            * 
            * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a directory
            * @param {Flags} options to create or excluively create the directory
            * @param {Function} successCallback is called with the new entry
            * @param {Function} errorCallback is called with a FileError
            */
            DirectoryEntry.prototype.getDirectory = function (path, options, successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "getDirectory", [this.fullPath, path, options]);
            };

            /**
            * Creates or looks up a file
            * 
            * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a file
            * @param {Flags} options to create or excluively create the file
            * @param {Function} successCallback is called with the new entry
            * @param {Function} errorCallback is called with a FileError
            */
            DirectoryEntry.prototype.getFile = function (path, options, successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "getFile", [this.fullPath, path, options]);
            };

            /**
            * Deletes a directory and all of it's contents
            * 
            * @param {Function} successCallback is called with no parameters
            * @param {Function} errorCallback is called with a FileError
            */
            DirectoryEntry.prototype.removeRecursively = function (successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "removeRecursively", [this.fullPath]);
            };

            /**
            * An interface that lists the files and directories in a directory.
            */
            DirectoryReader = function (fullPath) {
                this.fullPath = fullPath || null;
            };

            /**
            * Returns a list of entries from a directory.
            * 
            * @param {Function} successCallback is called with a list of entries
            * @param {Function} errorCallback is called with a FileError
            */
            DirectoryReader.prototype.readEntries = function (successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "readEntries", [this.fullPath]);
            }

            /**
            * An interface representing a directory on the file system.
            * 
            * {boolean} isFile always true (readonly)
            * {boolean} isDirectory always false (readonly)
            * {DOMString} name of the file, excluding the path leading to it (readonly)
            * {DOMString} fullPath the absolute full path to the file (readonly)
            * {FileSystem} filesystem on which the directory resides (readonly)
            */
            FileEntry = function () {
                this.isFile = true;
                this.isDirectory = false;
                this.name = null;
                this.fullPath = null;
                this.filesystem = null;
            };

            /**
            * Copies a file to a new location
            * 
            * @param {DirectoryEntry} parent the directory to which to copy the entry
            * @param {DOMString} newName the new name of the entry, defaults to the current name
            * @param {Function} successCallback is called with the new entry
            * @param {Function} errorCallback is called with a FileError
            */
            FileEntry.prototype.copyTo = function (parent, newName, successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "copyTo", [this.fullPath, parent, newName]);
            };

            /**
            * Looks up the metadata of the entry
            * 
            * @param {Function} successCallback is called with a Metadata object
            * @param {Function} errorCallback is called with a FileError
            */
            FileEntry.prototype.getMetadata = function (successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "getMetadata", [this.fullPath]);
            };

            /**
            * Gets the parent of the entry
            * 
            * @param {Function} successCallback is called with a parent entry
            * @param {Function} errorCallback is called with a FileError
            */
            FileEntry.prototype.getParent = function (successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "getParent", [this.fullPath]);
            };

            /**
            * Moves a directory to a new location
            * 
            * @param {DirectoryEntry} parent the directory to which to move the entry
            * @param {DOMString} newName the new name of the entry, defaults to the current name
            * @param {Function} successCallback is called with the new entry
            * @param {Function} errorCallback is called with a FileError
            */
            FileEntry.prototype.moveTo = function (parent, newName, successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "moveTo", [this.fullPath, parent, newName]);
            };

            /**
            * Removes the entry
            * 
            * @param {Function} successCallback is called with no parameters
            * @param {Function} errorCallback is called with a FileError
            */
            FileEntry.prototype.remove = function (successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "remove", [this.fullPath]);
            };

            /**
            * Returns a URI that can be used to identify this entry.
            * 
            * @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI.
            * @param {Function} successCallback is called with the new entry
            * @param {Function} errorCallback is called with a FileError
            */
            FileEntry.prototype.toURI = function (mimeType, successCallback, errorCallback) {
                return "file://localhost" + this.fullPath;
                //oPhoneGap.exec(successCallback, errorCallback, "File", "toURI", [this.fullPath, mimeType]);
            };

            /**
            * Creates a new FileWriter associated with the file that this FileEntry represents.
            * 
            * @param {Function} successCallback is called with the new FileWriter
            * @param {Function} errorCallback is called with a FileError
            */
            FileEntry.prototype.createWriter = function (successCallback, errorCallback) {
                this.file(function (filePointer) {
                    var writer = new FileWriter(filePointer);
                    if (writer.fileName == null || writer.fileName == "") {
                        if (typeof errorCallback == "function") {
                            errorCallback({
                                "code": FileError.INVALID_STATE_ERR
                            });
                        }
                    }
                    if (typeof successCallback == "function") {
                        successCallback(writer);
                    }
                }, errorCallback);
            };

            /**
            * Returns a File that represents the current state of the file that this FileEntry represents.
            * 
            * @param {Function} successCallback is called with the new File object
            * @param {Function} errorCallback is called with a FileError
            */
            FileEntry.prototype.file = function (successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, "File", "getFileMetadata", [this.fullPath]);
            };
            /**
            * Add the FileSystem interface into the browser.
            */
            //oPhoneGap.addConstructor(function() {
            var pgLocalFileSystem = new LocalFileSystem();
            // Needed for cast methods
            if (typeof window.localFileSystem == "undefined") window.localFileSystem = pgLocalFileSystem;
            if (typeof window.requestFileSystem == "undefined") window.requestFileSystem = pgLocalFileSystem.requestFileSystem;
            if (typeof window.resolveLocalFileSystemURI == "undefined") window.resolveLocalFileSystemURI = pgLocalFileSystem.resolveLocalFileSystemURI;
            //
            if (typeof window.oPhoneGap == "undefined") window.oPhoneGap = oPhoneGap;

            //});
        };
        if (!oPhoneGap.hasResource("filetransfer")) {
            oPhoneGap.addResource("filetransfer");

            /**
            * FileTransfer uploads a file to a remote server.
            */
            FileTransfer = function () { }

            /**
            * FileUploadResult
            */
            FileUploadResult = function () {
                this.bytesSent = 0;
                this.responseCode = null;
                this.response = null;
            }

            /**
            * FileTransferError
            */
            FileTransferError = function (errorCode) {
                this.code = errorCode || null;
            }

            FileTransferError.FILE_NOT_FOUND_ERR = 1;
            FileTransferError.INVALID_URL_ERR = 2;
            FileTransferError.CONNECTION_ERR = 3;

            /**
            * Given an absolute file path, uploads a file on the device to a remote server 
            * using a multipart HTTP request.
            * @param filePath {String}           Full path of the file on the device
            * @param server {String}             URL of the server to receive the file
            * @param successCallback (Function}  Callback to be invoked when upload has completed
            * @param errorCallback {Function}    Callback to be invoked upon error
            * @param options {FileUploadOptions} Optional parameters such as file name and mimetype           
            */
            FileTransfer.prototype.upload = function (filePath, server, successCallback, errorCallback, options) {
                if (!options.params) {
                    options.params = {};
                }
                options.filePath = filePath;
                options.server = server;
                if (!options.fileKey) {
                    options.fileKey = 'file';
                }
                if (!options.fileName) {
                    options.fileName = 'image.jpg';
                }
                if (!options.mimeType) {
                    options.mimeType = 'image/jpeg';
                }

                // successCallback required
                if (typeof successCallback != "function") {
                    console.log("FileTransfer Error: successCallback is not a function");
                    return;
                }


                // errorCallback optional
                if (errorCallback && (typeof errorCallback != "function")) {
                    console.log("FileTransfer Error: errorCallback is not a function");
                    return;
                }

                oPhoneGap.exec(successCallback, errorCallback, 'FileTransfer', 'upload', [options]);
            };
            /**
            * Downloads a file form a given URL and saves it to the specified directory.
            * @param source {String}          URL of the server to receive the file
            * @param target {String}         Full path of the file on the device
            * @param successCallback (Function}  Callback to be invoked when upload has completed
            * @param errorCallback {Function}    Callback to be invoked upon error
            */
            FileTransfer.prototype.download = function (source, target, successCallback, errorCallback) {
                oPhoneGap.exec(successCallback, errorCallback, 'FileTransfer', 'download', [source, target]);
            };
            FileTransfer.prototype._castTransferError = function (pluginResult) {
                var fileError = new FileTransferError(pluginResult.message);
                //fileError.code = pluginResult.message;
                pluginResult.message = fileError;
                return pluginResult;
            }

            FileTransfer.prototype._castUploadResult = function (pluginResult) {
                var result = new FileUploadResult();
                result.bytesSent = pluginResult.message.bytesSent;
                result.responseCode = pluginResult.message.responseCode;
                result.response = decodeURIComponent(pluginResult.message.response);
                pluginResult.message = result;
                return pluginResult;
            }

            /**
            * Options to customize the HTTP request used to upload files.
            * @param fileKey {String}   Name of file request parameter.
            * @param fileName {String}  Filename to be used by the server. Defaults to image.jpg.
            * @param mimeType {String}  Mimetype of the uploaded file. Defaults to image/jpeg.
            * @param params {Object}    Object with key: value params to send to the server.
            */
            FileUploadOptions = function (fileKey, fileName, mimeType, params) {
                this.fileKey = fileKey || null;
                this.fileName = fileName || null;
                this.mimeType = mimeType || null;
                this.params = params || null;
            }
            //oPhoneGap.addConstructor(function () {
            if (typeof navigator.fileTransfer == "undefined") navigator.fileTransfer = new FileTransfer();
            //});
        };
        //
        if (!oPhoneGap.hasResource("notification")) {
            oPhoneGap.addResource("notification");

            /**
            * This class provides access to notifications on the device.
            */
            Notification = function () {
            };

            /**
            * Open a native alert dialog, with a customizable title and button text.
            *
            * @param {String} message              Message to print in the body of the alert
            * @param {Function} completeCallback   The callback that is called when user clicks on a button.
            * @param {String} title                Title of the alert dialog (default: Alert)
            * @param {String} buttonLabel          Label of the close button (default: OK)
            */
            Notification.prototype.alert = function (message, completeCallback, title, buttonLabel) {
                var _title = (title || "Alert");
                var _buttonLabel = (buttonLabel || "OK");
                oPhoneGap.exec(completeCallback, null, "Notification", "alert", [message, { "title": _title, "buttonLabel": _buttonLabel}]);
            };

            /**
            * Open a native confirm dialog, with a customizable title and button text.
            * The result that the user selects is returned to the result callback.
            *
            * @param {String} message              Message to print in the body of the alert
            * @param {Function} resultCallback     The callback that is called when user clicks on a button.
            * @param {String} title                Title of the alert dialog (default: Confirm)
            * @param {String} buttonLabels         Comma separated list of the labels of the buttons (default: 'OK,Cancel')
            */
            Notification.prototype.confirm = function (message, resultCallback, title, buttonLabels) {
                var _title = (title || "Confirm");
                var _buttonLabels = (buttonLabels || "OK,Cancel");
                this.alert(message, resultCallback, _title, _buttonLabels);
            };
            /**
            * Start spinning the activity indicator on the statusbar
            */
            Notification.prototype.activityStart = function () {
                console.warn("Notification.activityStart is deprecated and will be removed in 1.0. It will be moved to the plugins repo.");
                oPhoneGap.exec(null, null, "Notification", "activityStart", []);
            };

            /**
            * Stop spinning the activity indicator on the statusbar, if it's currently spinning
            */
            Notification.prototype.activityStop = function () {
                console.warn("Notification.activityStop is deprecated and will be removed in 1.0. It will be moved to the plugins repo.");
                oPhoneGap.exec(null, null, "Notification", "activityStop", []);
            };

            /**
            * Causes the device to blink a status LED.
            * @param {Integer} count The number of blinks.
            * @param {String} colour The colour of the light.
            */
            Notification.prototype.blink = function (count, colour) {
                // NOT IMPLEMENTED	
            };

            Notification.prototype.vibrate = function (mills) {
                oPhoneGap.exec(null, null, "Notification", "vibrate", []);
            };

            Notification.prototype.beep = function (count, volume) {
                // No Volume yet for the iphone interface
                // We can use a canned beep sound and call that
                new Media('beep.wav').play();
            };

            //PhoneGap.addConstructor(function() {
            if (typeof navigator.notification == "undefined") navigator.notification = new Notification();
            //});



            this.PG = oPhoneGap;
        };

    },
    fail: function (evt) {
        var mensaje =
              'file.file.dowload fail:' +
              '' + evt.target.error.code + '';
        console.log(mensaje);
    },
    alertDismissed: function () {

    },
    loadUrl: function (url, props) {

    },
    exitApp: function () {
        //exit();
    },
    download: function (url) {
        try {
            var remoteFile = url;
            var localFileName = remoteFile.substring(remoteFile.lastIndexOf('/') + 1);

            window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fileSystem) {
                fileSystem.root.getFile(localFileName, { create: true, exclusive: false }, function (fileEntry) {
                    var localPath = fileEntry.fullPath;
                    if (device.platform === "Android" && localPath.indexOf("file://") === 0) {
                        localPath = localPath.substring(7);
                    }
                    var ft = new FileTransfer();
                    ft.download(remoteFile,
                    localPath, function (entry) {
                        //navigator.getCodeURL().setUrl(entry.fullPath);
                        var dwnldImg = document.getElementById("dwnldImg");
                        dwnldImg.href = 'page.html';
                        dwnldImg.style.visibility = "visible";
                        dwnldImg.style.display = "block";
                    }, this.fail);
                }, this.fail);
            }, this.fail);
            /*
            var dwnldImg = document.getElementById("dwnldImg");
            navigator.getCodeURL().setUrl(url);
            dwnldImg.href = 'page.html';
            dwnldImg.style.visibility = "visible";
            dwnldImg.style.display = "block";
            */
        }
        catch (e) {
            throw ('Ext.file.file.PhoneGap ' + e.message);

        }
    }
});
